﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;


namespace Moonwish.Silverlight.Controls
{
    /// <summary>
    /// 根据数据源自动生成树节点的树，by zhlin 2011-07-04
    /// </summary>
    public class SmartTreeView : TreeView
    {
        public new event RoutedPropertyChangedEventHandler<object> SelectedItemChanged;
        internal event SetItemSelectedEventHandler SetItemSelected;
        private Border _borderWait;

        public SmartTreeView()
        {
            IsAutoGenerate = true;

            DefaultStyleKey = typeof(TreeView);
        }

        protected override void OnSelectedItemChanged(RoutedPropertyChangedEventArgs<object> e)
        {
            SelectedItemDelayed = e.NewValue;
            ExpandDelayItems(e.NewValue);
            if (SelectedItemChanged != null)
            {
                SelectedItemChanged(this, e);
            }
        }

        protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems[0] is SmartTreeViewItem)
            {
                var newItem = (SmartTreeViewItem)e.NewItems[0];
                newItem.ParentTreeView = this;
            }
            base.OnItemsChanged(e);
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is SmartTreeView;
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new SmartTreeViewItem();
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _borderWait = (Border)GetTemplateChild("BorderWait");
        }

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            var treeViewItem = (SmartTreeViewItem)element;
            treeViewItem.ParentTreeView = this;

            base.PrepareContainerForItemOverride(element, item);

            if (item == SelectedItemDelayed)
            {
                _itemsToDelayExpand.Add(item);
            }
            InvokeContainerPrepared(treeViewItem, item);

            if (_borderWait != null && _borderWait.Visibility == Visibility.Visible)
            {
                _borderWait.Visibility = Visibility.Collapsed;
            }
        }

        public event RoutedEventHandler ContainerExpanded;
        internal void InvokeContainerExpanded(object sender, RoutedEventArgs e)
        {
            RoutedEventHandler expanded = ContainerExpanded;
            if (expanded != null) expanded(sender, e);
        }

        public event RoutedEventHandler ContainerCollapsed;
        internal void InvokeContainerCollapsed(object sender, RoutedEventArgs e)
        {
            RoutedEventHandler collapsed = ContainerCollapsed;
            if (collapsed != null) collapsed(sender, e);
        }

        public event MouseButtonEventHandler ContainerMouseLeftButtonDownEventHandler;
        internal void InvokeContainerMouseLeftButtonButtonEventHandler(object sender, MouseButtonEventArgs e)
        {
            MouseButtonEventHandler handler = ContainerMouseLeftButtonDownEventHandler;
            if (handler != null) handler(sender, e);
        }

        public event EventHandler<ContainerPreparedEventArgs> ContainerPrepared;
        internal void InvokeContainerPrepared(SmartTreeViewItem sender, object item)
        {
            EventHandler<ContainerPreparedEventArgs> prepared = ContainerPrepared;
            if (prepared != null) prepared(sender, new ContainerPreparedEventArgs(sender, item));

            if (_itemsToDelayExpand.Contains(item))
            {
                //sender.IsExpanded = true;
                sender.IsSelected = true;
                _itemsToDelayExpand.Remove(item);
            }
        }

        private List<object> _itemsToDelayExpand = new List<object>();
        public void ExpandDelayItems(params object[] itemsCorrespondingToTreeViewItemsToExpand)
        {
            foreach (var item in itemsCorrespondingToTreeViewItemsToExpand)
            {
                if (!_itemsToDelayExpand.Contains(item))
                {
                    _itemsToDelayExpand.Add(item);
                }
            }

            foreach (object itemtoTryAndExpand in itemsCorrespondingToTreeViewItemsToExpand)
            {
                TreeViewItem treeViewItem = this.ContainerFromItem(itemtoTryAndExpand);
                if (treeViewItem != null)
                {
                    treeViewItem.IsSelected = true; 
                    _itemsToDelayExpand.Remove(itemtoTryAndExpand);
                }
            }
        }

        /// <summary>
        /// 是否自动生成树节点。
        /// </summary>
        public bool IsAutoGenerate
        {
            get;
            set;
        }

        protected object SelectedItemDelayed;
        public new object SelectedItem
        {
            get
            {
                var ret = this.ContainerFromItem(SelectedItemDelayed);
                if (ret == null && SelectedItemDelayed != null)
                {
                    ret = new TreeViewItem();
                    ret.DataContext = SelectedItemDelayed;
                }
                return ret;
            }
            set
            {
                SelectedItemDelayed = value;
                var node = this.ContainerFromItem(SelectedItemDelayed);
                if (node != null)
                {
                    ContainerPrepared += ContainerPrepared_LookForSelectedItem;
                    ExpandDelayItems(SelectedItemDelayed);
                }
                if (SetItemSelected != null && SelectedItemDelayed != null)
                {
                    var e = new SetItemSelectedEventArgs();
                    e.Item = SelectedItemDelayed;
                    SetItemSelected(e);
                }
            }
        }

        private bool _selectedIsReached;
        public void SetSelectedByPath(object rootObj, object targetObj)
        {
            _selectedIsReached = false;
            Dispatcher.BeginInvoke(new ThreadStart(() => SelectPath(rootObj, targetObj)));
        }

        private void SelectPath(object rootObj, object targetObj)
        {
            var item = this.ContainerFromItem(rootObj);
            if (item == null || _selectedIsReached)
            {
                return;
            }
            bool justExpanded = !item.IsExpanded;
            item.IsExpanded = true;
            if (item.DataContext == targetObj)
            {
                item.IsSelected = true;
                return;
            }
            if (justExpanded)
            {
                item.Dispatcher.BeginInvoke(new ThreadStart(() => SelectPath(rootObj, targetObj)));
            }
            else
            {
                for (int i = 0; i < item.Items.Count; i++)
                {
                    var child = item.ItemContainerGenerator.ContainerFromIndex(i) as SmartTreeViewItem;
                    if (child != null)
                    {
                        if (child.DataContext == targetObj)
                        {
                            child.IsExpanded = true;
                            child.IsSelected = true;
                            _selectedIsReached = true;
                            EnsureUniquePath(child);
                            return;
                        }
                        SelectPath(child.DataContext, targetObj);
                    }
                }
            }
        }

        private void EnsureUniquePath(SmartTreeViewItem selectedItem)
        {
            var parent = selectedItem.ParentTreeViewItem;
            if (parent == null)
            {
                return;
            }
            foreach (var child in parent.Items)
            {
                var brother = (SmartTreeViewItem)parent.ItemContainerGenerator.ContainerFromItem(child);
                if (brother != selectedItem)
                {
                    brother.IsExpanded = false;
                }
                else
                {
                    EnsureUniquePath(parent);
                }
            }
        }

        private void ContainerPrepared_LookForSelectedItem(object sender, ContainerPreparedEventArgs e)
        {
            if (e.Item == SelectedItemDelayed)
            {
                e.Container.IsSelected = true;
                e.Container.IsExpanded = true;
                SelectedItemDelayed = null;
                ContainerPrepared -= ContainerPrepared_LookForSelectedItem;
            }
        }

        /// <summary>
        /// 迭代数据源名称。
        /// </summary>
        public string HierarchicalSourceName
        {
            get;
            set;
        }

        /// <summary>
        /// 树节点图片。
        /// </summary>
        public string TreeNodeImagePath
        {
            get;
            set;
        }
    }
}
